﻿using Modbus.Device;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO.Ports;
using System.Timers;
using System.Windows.Forms;
using System;

namespace HenhouseEnvironmentCtrl
{
    public partial class HomeForm : Form
    {
        int hour = 0, minute = 0, second = 0; // 定时上传的时间参数
        SerialPort port = null; // 串口对象
        IModbusSerialMaster master = null; // Modbus主站对象
        System.Timers.Timer timer = new System.Timers.Timer(); // 实时接收数据的定时器
        System.Timers.Timer warn = new System.Timers.Timer(); // 警告监测的定时器
        System.Timers.Timer timeclock = new System.Timers.Timer(); // 定时上传的定时器
        System.Timers.Timer writeTimer = new System.Timers.Timer(); // 定时写入数据的定时器

        // 公共属性，允许外部访问master和port对象
        public IModbusSerialMaster Master { get { return master; } }
        public SerialPort Port { get { return port; } }

        public HomeForm()
        {
            InitializeComponent();
        }

        // 窗体加载事件处理函数
        private void HomeForm_Load(object sender, EventArgs e)
        {
            lblUserNow.Text = DBConnection.User.Name; // 显示当前登录用户名
            timer1.Start(); // 启动显示当前时间的定时器
            InitializeSystem(); // 初始化系统
        }

        // 初始化系统
        private void InitializeSystem()
        {
            List<string> henhouseList = new List<string>(); // 存储鸡舍列表
            using (SqlConnection conn = DBConnection.CreateConnection())
            {
                DBConnection.Open(conn); // 打开数据库连接
                SqlCommand cmd = new SqlCommand("SELECT * FROM Henhouse", conn); // 查询所有鸡舍信息
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        henhouseList.Add(reader["HenhouseName"].ToString()); // 将鸡舍名称添加到列表中
                    }
                }
            }
            cboHenhouse.DataSource = henhouseList; // 将鸡舍列表绑定到下拉框

            try
            {
                // 初始化串口
                port = new SerialPort
                {
                    BaudRate = 9600,
                    Parity = Parity.None,
                    DataBits = 8,
                    StopBits = StopBits.One,
                    PortName = "COM1"
                };
                master = ModbusSerialMaster.CreateRtu(port); // 创建Modbus RTU主站对象
                if (!port.IsOpen)
                {
                    port.Open(); // 打开串口
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message); // 显示错误信息
                return;
            }

            SetupTimers(); // 设置定时器
        }

        // 设置定时器
        private void SetupTimers()
        {
            timer.Interval = 1000; // 设置1秒的时间间隔
            timer.AutoReset = true; // 自动重置
            timer.Elapsed += Timer_Elapsed; // 绑定定时器事件
            timer.Start(); // 启动定时器

            warn.Interval = 20000; // 设置20秒的时间间隔
            warn.AutoReset = true; // 自动重置
            warn.Elapsed += Warn_Elapsed; // 绑定定时器事件
            warn.Start(); // 启动定时器

            timeclock.Interval = 1000; // 设置3秒的时间间隔
            timeclock.AutoReset = true; // 自动重置
            timeclock.Elapsed += Timeclock_Elapsed; // 绑定定时器事件
            timeclock.Start(); // 启动定时器

            writeTimer.Interval = 3000; // 设置3秒的时间间隔
            writeTimer.AutoReset = true; // 自动重置
            writeTimer.Elapsed += WriteTimer_Elapsed; // 绑定定时器事件
            writeTimer.Start(); // 启动定时器
        }

        // 定时写入数据
        private void WriteTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            WriteDataToSlaves(); // 写入数据到从站
        }

        // 写入数据到从站
        private void WriteDataToSlaves()
        {
            if (port != null && port.IsOpen)
            {
                Random random = new Random();

                foreach (byte slaveId in GetAllIds())
                {
                    ushort[] environmentData = master.ReadHoldingRegisters(slaveId, 0, 5); // 读取保持寄存器数据
                    float currentTemp = environmentData[0] / 10.0f;
                    float currentHumidity = environmentData[1] / 10.0f;
                    int currentPM25 = environmentData[2];
                    int currentNH3 = environmentData[3];
                    float currentCO2 = environmentData[4] / 10.0f;

                    // 随机生成环境数据变化
                    float tempChange = (float)(random.NextDouble() * 2 - 1);
                    float humidityChange = (float)(random.NextDouble() * 2 - 1);
                    int pm25Change = random.Next(-5, 6);
                    int nh3Change = random.Next(-2, 3);
                    float co2Change = (float)(random.NextDouble() * 10 - 5);

                    currentTemp += tempChange;
                    currentHumidity += humidityChange;
                    currentPM25 += pm25Change;
                    currentNH3 += nh3Change;
                    currentCO2 += co2Change;

                    // 限制数据范围
                    currentTemp = Math.Max(Math.Min(currentTemp, 40), 0);
                    currentHumidity = Math.Max(Math.Min(currentHumidity, 100), 0);
                    currentPM25 = Math.Max(Math.Min(currentPM25, 500), 0);
                    currentNH3 = Math.Max(Math.Min(currentNH3, 100), 0);
                    currentCO2 = Math.Max(Math.Min(currentCO2, 5000), 0);

                    // 四舍五入
                    currentTemp = (float)Math.Round(currentTemp, 2);
                    currentHumidity = (float)Math.Round(currentHumidity, 2);

                    ushort[] data = new ushort[5]
                    {
                        (ushort)(currentTemp * 10),
                        (ushort)(currentHumidity * 10),
                        (ushort)currentPM25,
                        (ushort)currentNH3,
                        (ushort)(currentCO2 * 10)
                    };

                    try
                    {
                        master.WriteMultipleRegisters(slaveId, 0, data); // 写入数据到从站
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("写入数据失败: " + ex.Message); // 显示错误信息
                    }
                }
            }
        }

        // 定时器事件处理函数，用于警告监测
        private void Warn_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (port != null && port.IsOpen)
            {
                MonitorWarnings(); // 监测警告
            }
        }

        // 定时器事件处理函数，用于实时接收数据
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            byte date = 0;
            this.Invoke(new Action(() =>
            {
                date = GetId(); // 获取当前选择的鸡舍ID
            }));

            if (port != null && port.IsOpen)
            {
                try
                {
                    ushort[] uDatas = master.ReadHoldingRegisters(date, 0, 5); // 读取保持寄存器数据
                    if (uDatas != null && uDatas.Length > 0)
                    {
                        float tem = uDatas[0] / 10F;
                        float hum = uDatas[1] / 10F;
                        int pm25 = uDatas[2];
                        int nh3 = uDatas[3];
                        int co2 = uDatas[4];

                        this.Invoke(new Action(() =>
                        {
                            // 更新界面数据
                            gaugeTemp.Value = Math.Round(tem, 2);
                            gaugeHumidity.Value = Math.Round(hum, 2);
                            gaugePM25.Value = pm25;
                            gaugeNH3.Value = nh3;
                            gaugeCO2.Value = co2;
                            lblTemp.Text = Math.Round(tem, 2).ToString("0.00") + "℃";
                            lblHumidity.Text = Math.Round(hum, 2).ToString("0.00") + "%rh";
                            lblPM25.Text = pm25.ToString() + "μg/m³";
                            lblNH3.Text = nh3.ToString() + "ppm";
                            lblCO2.Text = co2.ToString() + "ppm";
                        }));

                        // 保存传感器数据到数据库
                        DBConnection.SaveSensorData("InternalEnvironment", new float[] { tem, hum, pm25, nh3, co2 }, DateTime.Now.ToString("yyyy-MM-dd"), DateTime.Now.ToString("HH:mm:ss"), cboHenhouse.Text);
                    }
                    else
                    {
                        MessageBox.Show("连接已断开"); // 显示错误信息
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("出现错误: " + ex.Message); // 显示错误信息
                }
            }
        }

        // 获取当前选择的鸡舍ID
        public byte GetId()
        {
            byte bit = 0;
            using (SqlConnection conn = DBConnection.CreateConnection())
            {
                DBConnection.Open(conn);
                SqlCommand cmd = new SqlCommand($"SELECT HenhouseId FROM Henhouse WHERE HenhouseName='{cboHenhouse.Text}'", conn);
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    if (dr.Read())
                    {
                        bit = (byte)int.Parse(dr["HenhouseId"].ToString());
                    }
                }
            }
            return bit;
        }

        // 历史数据按钮点击事件
        private void BtnHistoryData_Click(object sender, EventArgs e)
        {
            this.Hide();
            HistoryForm historyForm = new HistoryForm();
            historyForm.ShowDialog();
            this.Show();
        }

        // 获取所有鸡舍的ID
        private byte[] GetAllIds()
        {
            List<byte> data = new List<byte>();
            using (SqlConnection conn = DBConnection.CreateConnection())
            {
                DBConnection.Open(conn);
                SqlCommand cmd = new SqlCommand($"SELECT HenhouseId FROM Henhouse", conn);
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        data.Add(byte.Parse(dr["HenhouseId"].ToString()));
                    }
                }
            }
            return data.ToArray();
        }

        // 获取对应鸡舍ID的表名
        // 根据HenhouseId获取对应的鸡舍名称
        private string GetHenhouseName(byte henhouseId)
        {
            string henhouseName = null;
            using (SqlConnection conn = DBConnection.CreateConnection())
            {
                DBConnection.Open(conn);
                SqlCommand cmd = new SqlCommand($"SELECT HenhouseName FROM Henhouse WHERE HenhouseId={henhouseId}", conn);
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    if (dr.Read())
                    {
                        henhouseName = dr["HenhouseName"].ToString();
                    }
                }
            }
            return henhouseName;
        }


        // 监测警告
        private void MonitorWarnings()
        {
            byte[] bt = GetAllIds();
            DateTime dt = DateTime.Now;
            string date = dt.ToString("yyyy-MM-dd");
            string time = dt.ToString("HH:mm:ss");

            foreach (byte id in bt)
            {
                bool temWarn = false, humWarn = false, pm25Warn = false, nh3Warn = false, co2Warn = false;
                try
                {
                    ushort[] uDatas = master.ReadHoldingRegisters(id, 0, 5);
                    if (uDatas != null && uDatas.Length > 0)
                    {
                        float tem = uDatas[0] / 10F;
                        float hum = uDatas[1] / 10F;
                        int pm25 = uDatas[2];
                        int nh3 = uDatas[3];
                        int co2 = uDatas[4];
                        using (SqlConnection conn = DBConnection.CreateConnection())
                        {
                            DBConnection.Open(conn);
                            SqlCommand cmd = new SqlCommand($"SELECT * FROM Henhouse WHERE HenhouseId={id}", conn);
                            using (SqlDataReader dr = cmd.ExecuteReader())
                            {
                                if (dr.Read())
                                {
                                    string henhouseName = dr["HenhouseName"].ToString();
                                    if (float.Parse(dr["TempMax"].ToString()) < tem || float.Parse(dr["TempMin"].ToString()) > tem)
                                    {
                                        MessageBox.Show(henhouseName + " 温度报警");
                                        temWarn = true;
                                    }
                                    if (float.Parse(dr["HumMax"].ToString()) < hum || float.Parse(dr["HumMin"].ToString()) > hum)
                                    {
                                        MessageBox.Show(henhouseName + " 湿度报警");
                                        humWarn = true;
                                    }
                                    if (int.Parse(dr["PM25Max"].ToString()) < pm25 || int.Parse(dr["PM25Min"].ToString()) > pm25)
                                    {
                                        MessageBox.Show(henhouseName + " PM2.5报警");
                                        pm25Warn = true;
                                    }
                                    if (int.Parse(dr["NH3Max"].ToString()) < nh3 || int.Parse(dr["NH3Min"].ToString()) > nh3)
                                    {
                                        MessageBox.Show(henhouseName + " NH3报警");
                                        nh3Warn = true;
                                    }
                                    if (int.Parse(dr["CO2Max"].ToString()) < co2 || int.Parse(dr["CO2Min"].ToString()) > co2)
                                    {
                                        MessageBox.Show(henhouseName + " CO2报警");
                                        co2Warn = true;
                                    }
                                }

                                if (temWarn || humWarn || pm25Warn || nh3Warn || co2Warn)
                                {
                                    dr.Close();
                                    SqlCommand com1 = new SqlCommand();
                                    com1.Connection = conn;
                                    if (temWarn)
                                    {
                                        com1.CommandText = $"INSERT INTO WarnRecord (HenhouseName, WarnType, Date, Time) VALUES ('{cboHenhouse.Text}', '温度报警', '{date}', '{time}')";
                                        com1.ExecuteNonQuery();
                                    }
                                    if (humWarn)
                                    {
                                        com1.CommandText = $"INSERT INTO WarnRecord (HenhouseName, WarnType, Date, Time) VALUES ('{cboHenhouse.Text}', '湿度报警', '{date}', '{time}')";
                                        com1.ExecuteNonQuery();
                                    }
                                    if (pm25Warn)
                                    {
                                        com1.CommandText = $"INSERT INTO WarnRecord (HenhouseName, WarnType, Date, Time) VALUES ('{cboHenhouse.Text}', 'PM2.5报警', '{date}', '{time}')";
                                        com1.ExecuteNonQuery();
                                    }
                                    if (nh3Warn)
                                    {
                                        com1.CommandText = $"INSERT INTO WarnRecord (HenhouseName, WarnType, Date, Time) VALUES ('{cboHenhouse.Text}', 'NH3报警', '{date}', '{time}')";
                                        com1.ExecuteNonQuery();
                                    }
                                    if (co2Warn)
                                    {
                                        com1.CommandText = $"INSERT INTO WarnRecord (HenhouseName, WarnType, Date, Time) VALUES ('{cboHenhouse.Text}', 'CO2报警', '{date}', '{time}')";
                                        com1.ExecuteNonQuery();
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    timer.Stop();
                    warn.Stop();
                    timer1.Stop();
                    timeclock.Stop();
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        // 上传数据到数据库
        private void UploadData()
        {
            byte[] bt = GetAllIds();
            if (port == null || !port.IsOpen)
                port.Open();

            foreach (byte id in bt)
            {
                DateTime dt = DateTime.Now;
                string date = dt.ToString("yyyy-MM-dd");
                string time = dt.ToString("HH:mm:ss");

                try
                {
                    ushort[] uDatas = master.ReadHoldingRegisters(id, 0, 5);
                    float tem = uDatas[0] / 10F;
                    float hum = uDatas[1] / 10F;
                    int pm25 = uDatas[2];
                    int nh3 = uDatas[3];
                    int co2 = uDatas[4];

                    string tableName = GetHenhouseName(id);
                    using (SqlConnection conn = DBConnection.CreateConnection())
                    {
                        DBConnection.Open(conn);
                        SqlCommand cmd = new SqlCommand($"INSERT INTO InternalEnvironment (Date, Temp, Humidity, PM25, NH3, CO2, Time) VALUES ('{date}', {tem}, {hum}, {pm25}, {nh3}, {co2}, '{time}')", conn);
                        cmd.ExecuteNonQuery();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("上传出现问题: " + ex);
                    return;
                }
            }
            MessageBox.Show("上传成功");
        }

        // 上传按钮点击事件
        private void BtnUpload_Click(object sender, EventArgs e)
        {
            UploadData();
        }

        // 退出按钮点击事件
        private void BtnExit_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            Environment.Exit(0);
        }

        // 窗体关闭事件处理函数
        private void HomeForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer.Stop();
            timer1.Stop();
            warn.Stop();
        }

        // 警告记录按钮点击事件
        private void BtnWarningRecord_Click(object sender, EventArgs e)
        {
            this.Hide();
            HistoryWarningDataForm formWarnRecord = new HistoryWarningDataForm();
            formWarnRecord.ShowDialog();
            this.Show();
        }

        // 警告设置按钮点击事件
        private void BtnWarningSet_Click(object sender, EventArgs e)
        {
            SetWarningForm formWarnSet = new SetWarningForm();
            formWarnSet.ShowDialog();
        }

        // 设备管理按钮点击事件
        private void BtnDeviceManage_Click(object sender, EventArgs e)
        {
            this.Hide();
            EquipmentCtrlForm equipmentCtrlForm = new EquipmentCtrlForm(master, port);
            equipmentCtrlForm.ShowDialog();
            this.Show();
        }

        // 定时上传设置按钮点击事件
        private void BtnAutoUpload_Click(object sender, EventArgs e)
        {
            if (!int.TryParse(txtHour.Text, out hour))
            {
                MessageBox.Show("请输入正确信息");
                return;
            }
            if (!int.TryParse(txtMinute.Text, out minute))
                minute = 0;
            if (!int.TryParse(txtSecond.Text, out second))
                second = 0;
            if ((hour < 0 || hour > 24) || minute < 0 || minute > 60 || second < 0 || second > 60)
            {
                MessageBox.Show("请输入合适数据");
                return;
            }
            if (hour == 0 && minute == 0 && second == 0)
            {
                MessageBox.Show("请输入合适数据");
                return;
            }
            timeclock.Start();
            MessageBox.Show("定时上传已设置成功");
        }

        // 定时器事件处理函数，用于定时上传数据
        private void Timeclock_Elapsed(object sender, ElapsedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            if (dt.Hour == hour && dt.Minute == minute && dt.Second == second)
                UploadData();
        }

        // 实时图表按钮点击事件
        private void BtnChartData_Click(object sender, EventArgs e)
        {
            this.Hide();
            ChartDataForm chartDataForm = new ChartDataForm(master, port);
            chartDataForm.ShowDialog();
            this.Show();
        }

        private void btnSetInterval_Click(object sender, EventArgs e)
        {
            int interval ;
            if (!int.TryParse(this.txtIntervelSecond.Text, out interval))
            {
                MessageBox.Show("请输入正确信息");
                return;
            }
            timer.Interval = interval * 1000;
            MessageBox.Show("上传间隔时间设置成功", "提示");
        }






        // 设置理想环境按钮点击事件
        private void BtnSetEnvironment_Click(object sender, EventArgs e)
        {
            SetIdealEnvironment();
        }

        // 设置理想环境参数
        private void SetIdealEnvironment()
        {
            if (port != null && port.IsOpen)
            {
                foreach (byte slaveId in GetAllIds())
                {
                    float idealTemp = 25.0f;
                    float idealHumidity = 60.0f;

                    ushort[] data = new ushort[2]
                    {
                        (ushort)(idealTemp * 10),
                        (ushort)(idealHumidity * 10)
                    };

                    try
                    {
                        master.WriteMultipleRegisters(slaveId, 0, data); // 写入理想环境参数
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("写入数据失败: " + ex.Message);
                        return;
                    }
                }
                MessageBox.Show("一键控温成功！","提示");
            }
        }
    }
}
